home *** CD-ROM | disk | FTP | other *** search
/ Hyper Stacks 1994 May / Hyper Stacks (Pacific HiTech)(1994)[Mac].iso / HyperTalk / FileName / FileName.p < prev   
Encoding:
Text File  |  1987-11-18  |  8.5 KB  |  280 lines  |  [TEXT/MPS ]

  1. {
  2. FileName:      A HyperCard "XFCN" (External Function) Resource
  3.                         Version 1.11
  4.  
  5. Written By: Steve Maller
  6.                          Apple Computer Training Support
  7.                          Copyright © 1987 Apple Computer
  8.                          AppleLink: MALLER1
  9.                          Saturday, August 22, 1987 - 1.0
  10.                         Tuesday, November 17, 1987 - 1.1 - smart window centering
  11.                         Wednesday, November 18, 1987 - 1.11 - fixed initialization bug
  12.  
  13. Language:        MPW Pascal (with a little English thrown in for good measure )
  14.  
  15. To build:        pascal FileName.p
  16.                         link -m ENTRYPOINT -rt XFCN=913 -sn Main=FileName ∂
  17.                             -t STAK -c WILD ∂
  18.                             FileName.p.o ∂
  19.                             hd:dev:mpw:libraries:Interface.o ∂
  20.                             hd:dev:mpw:PLibraries:Paslib.o ∂
  21.                             -o "FileName XFCN"
  22.  
  23. Usage:            FileName("fileType")    -- "fileType" is optional
  24.  
  25. Examples:        FileName("STAK")            -- limits list to HyperCard Stacks
  26.                         FileName("TEXT")            -- limits list to text files
  27.                         FileName("APPL")            -- limits list to applications
  28.                         FileName()                      -- lists ALL files
  29.  
  30. Result:            The full pathname of the selected file.
  31.                         For example, if you selected the file "Address Stack" which is
  32.                         in the folder "My Stacks" in the folder "HyperCard" on the
  33.                         disk "HD" the result is:
  34.                                     HD:HyperCard:My Stacks:Address Stack
  35.                         
  36. Warning:        A word of caution: the Mac’s file system can NOT accept
  37.                         pathnames longer than 255 characters. Be careful...
  38.                         
  39. Script
  40. Example:        on mouseUp
  41.                             put FileName("TEXT") into theFile
  42.                             if theFile is not empty then
  43.                                 open file theFile
  44.                                 read from file theFile for 2000
  45.                                 put it into bkgnd field 1
  46.                                 close file theFile
  47.                             end if
  48.                         end mouseUp
  49.  
  50. Why?                You must access files in HyperCard by their full pathname.
  51.                         Unfortunately, HyperCard offers you no clear way of finding
  52.                         out what that full name is. If files are on a hard disk, it
  53.                         can be a real pain to remember the entire pathname. This
  54.                         function simplifies that task for both the stackware developer
  55.                         and the end user.
  56.  
  57. Thanks to:    The HyperCard Team - my heros!
  58.  
  59. }
  60.  
  61. {$S FileName }
  62.  
  63. UNIT Snoopy_Vs_TheRedBaron; { obviously this name is irrelevant }
  64.  
  65. { =----------------------INTERFACE----------------------= }
  66.  
  67.     INTERFACE
  68.  
  69.         USES
  70.             {$LOAD PasSymDump}
  71.             MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, HyperXCmd;
  72.  
  73.         PROCEDURE EntryPoint(paramPtr: XCmdPtr);
  74.  
  75. { =----------------------IMPLEMENTATION----------------------= }
  76.  
  77.     IMPLEMENTATION
  78.  
  79.         {$R-}                    
  80.         { no Pascal range checking }
  81.  
  82.         TYPE
  83.             Str31 = String[31];                    { for the glue file “XCmdGlue.inc” }
  84.  
  85.         PROCEDURE FileName(paramPtr: XCmdPtr);
  86.             FORWARD;
  87.  
  88.                 { =----------------------EntryPoint----------------------= }
  89.  
  90.         PROCEDURE EntryPoint(paramPtr: XCmdPtr);
  91.  
  92.             BEGIN
  93.                 FileName(paramPtr);
  94.             END;
  95.  
  96.                 { =----------------------FileName----------------------= }
  97.  
  98.         PROCEDURE FileName(paramPtr: XCmdPtr);
  99.  
  100.             VAR
  101.                 myWDPB: WDPBPtr; { some variants of the same animal }
  102.                 myCPB: CInfoPBPtr;
  103.                 myPB: HParmBlkPtr;
  104.                 fullPathName: Str255;
  105.                 numTypes: Integer;
  106.                 reply: SFReply;
  107.                 typeList: SFTypeList;
  108.  
  109.                 {$I XCmdGlue.inc }
  110.  
  111.                 { =----------------------CenterWindow----------------------= }
  112.  
  113.             PROCEDURE CenterWindow(w: WindowPtr);
  114.             
  115.             { a general-purpose routine that will center the window who’s 
  116.                 WindowPtr is passed in w. Here it is used to center the still-
  117.                 invisible SFGetFile dialog box. We’ll just steal the coordinates
  118.                 of the upper-left corner of the dialog to pass to SFGetFile... }
  119.  
  120.                 VAR
  121.                     hWindSize: Integer;
  122.                     vWindSize: Integer;
  123.                     hSize: Integer;
  124.                     vSize: Integer;
  125.  
  126.                 BEGIN
  127.                     WITH w^.portBits.bounds DO        { find out how big the SCREEN is }
  128.                         BEGIN
  129.                             hSize := right - left;        { NOTE: this centers the window }
  130.                             vSize := bottom - top;        { within screenBits.bounds ONLY. }
  131.                         END;                                                { It will NOT recognize multiple }
  132.                                                                                 { monitors on a Mac II... } 
  133.                     WITH w^.portRect DO
  134.                         BEGIN
  135.                             hWindSize := right - left;    { get the size of the window }
  136.                             vWindSize := bottom - top;
  137.                         END;
  138.                         
  139.                     { now move the window to the appropriate place on the screen }
  140.  
  141.                     MoveWindow(w, ((hSize - hWindSize) DIV 2),
  142.                                                 ((vSize - vWindSize + 20) DIV 2), FALSE);
  143.                 END;
  144.  
  145.             { =----------------------TheyChoseAFile----------------------= }
  146.  
  147.             FUNCTION TheyChoseAFile: Boolean;
  148.  
  149.                 VAR
  150.                     pt: Point;
  151.                     wPtr: WindowPtr;
  152.                     savePort: WindowPtr;
  153.  
  154.                 BEGIN
  155.                     TheyChoseAFile := FALSE;
  156.  
  157.                     GetPort(savePort);                            { save the current grafport }
  158.                     
  159.                     { load in the SFGetFile DLOG resource for perousal }
  160.                     
  161.                     wPtr := GetNewDialog(getDlgID, NIL, POINTER( - 1));
  162.  
  163.                     SetPort(wPtr);                                    { set port to it for LocalToGlobal }
  164.                     CenterWindow(wPtr);                            { center (still invisible) window }
  165.                     pt := wPtr^.portRect.topLeft;        { is 0,0 - but no assumptions! }
  166.                     LocalToGlobal(pt);                            { convert this into global coords }
  167.  
  168.                     SFGetFile(pt, '', NIL, numTypes, typeList, NIL, reply);
  169.                     { have ’em pick a file }
  170.  
  171.                     SetPort(savePort);                            { restore the grafport }
  172.  
  173.                     IF reply.good THEN { if they didn’t choose Cancel }
  174.                         BEGIN
  175.                             TheyChoseAFile := TRUE;
  176.                             fullPathName := reply.fName; { start the ball rolling }
  177.                         END;
  178.                 END;
  179.  
  180.             { =----------------------BuildThePathName----------------------= }
  181.  
  182.             PROCEDURE BuildThePathName;
  183.  
  184.                 VAR
  185.                     name: Str255;
  186.                     err: Integer;
  187.  
  188.                 BEGIN
  189.                     name := '';                                                     { start with an empty name }
  190.                     myPB^.ioNamePtr := @name;                         { we want the Volume name }
  191.                     myPB^.ioCompletion := POINTER(0);
  192.                     myPB^.ioVRefNum := reply.vRefNum;         { returned from SFGetFile }
  193.                     myPB^.ioVolIndex := 0;                                 { use the vRefNum and name }
  194.                     err := PBHGetVInfo(myPB, FALSE);             { fill in the Volume info }
  195.                     IF err <> noErr THEN
  196.                         Exit(FileName);
  197.  
  198. { Now we need the Working Directory (WD) information because we’re going
  199.  to step backwards from the file through all of the the folders until
  200.  we reach the root directory }
  201.  
  202.                     myWDPB^.ioVRefNum := reply.vRefNum;     { this got set to 0 above }
  203.                     myWDPB^.ioWDProcID := 0;                             { use the vRefNum }
  204.                     myWDPB^.ioWDIndex := 0;                             { we want ALL directories }
  205.                     err := PBGetWDInfo(myWDPB, FALSE);         { do it }
  206.                     IF err <> noErr THEN
  207.                         Exit(FileName);
  208.  
  209.                     myCPB^.ioFDirIndex := - 1;                         { use the ioDirID field only }
  210.                     myCPB^.ioDrDirID := myWDPB^.ioWDDirID; { info returned above }
  211.                     err := PBGetCatInfo(myCPB, FALSE);         { do it }
  212.                     IF err <> noErr THEN
  213.                         Exit(FileName);
  214.  
  215. { Here starts the real work - start to climb the tree by continually
  216.  looking in the ioDrParId field for the next directory above until we
  217.  fail... }
  218.  
  219.                     myCPB^.ioDrDirID := myCPB^.ioDrParId;         { the first folder}
  220.                     fullPathName := Concat(myCPB^.ioNamePtr^, ':', reply.fName);
  221.                     REPEAT
  222.                         myCPB^.ioDrDirID := myCPB^.ioDrParId;
  223.                         err := PBGetCatInfo(myCPB, FALSE);             { the next level }
  224.  
  225. { Be careful of an error returned here - it means the user chose a file
  226.  on the desktop level of this volume. If this is the case, just stop
  227.  here and return "VolumeName:FileName", otherwise loop until failure }
  228.                         IF err = noErr THEN
  229.                             fullPathName := Concat(myCPB^.ioNamePtr^, ':', fullPathName);
  230.  
  231.                     UNTIL err <> noErr;
  232.  
  233.                 END; { PROCEDURE BuildThePathName }
  234.  
  235.             { =---------------------- * FileName * ----------------------= }
  236.  
  237.             BEGIN { PROCEDURE FileName }
  238.  
  239. { First we allocate some memory in the heap for the parameter block. This
  240.  could in theory work on the stack, but in reality it makes no difference
  241.  as we’re entirely modal (ugh) here... }
  242.  
  243.                 fullPathName := '';
  244.  
  245.                 myCPB := CInfoPBPtr(NewPtr(SizeOf(HParamBlockRec)));
  246.                 IF ord4(myCPB) <= 0 THEN
  247.                     Exit(FileName);                             { Rats! Bill didn’t leave enough room }
  248.                 myWDPB := WDPBPtr(myCPB);             { icky Pascal type coercions... }
  249.                 myPB := HParmBlkPtr(myCPB);
  250.  
  251.                 numTypes := 1;                                     { for SFGetFile }
  252.                 WITH paramPtr^ DO
  253.                     BEGIN
  254.                         IF paramCount = 0 THEN
  255.                             numTypes := - 1                     { FileName() - get all files }
  256.                         ELSE
  257.                             BlockMove(params[1]^, @typeList[0], 4);
  258.                                                                                 { FileName("TYPE") }
  259.  
  260.                         IF TheyChoseAFile THEN
  261.                             BuildThePathName;
  262.  
  263. { PasToZero is very interesting - it is a HyperTalk command
  264.  that you can actually call from OUTSIDE of HyperCard.
  265.  You need it because HyperCard uses C format strings with
  266.  no length byte; they are terminated by a null byte. They are
  267.  actually HANDLES to C format strings. Nice work, Dan! }
  268.  
  269.                         returnValue := PasToZero(fullPathName);
  270.  
  271.                     END; { WITH paramPtr^ DO }
  272.  
  273.                 DisposPtr(POINTER(myCPB));             { Thou Shalt Clean Up Thy Heap! }
  274.                 
  275.                 numTypes := StringWidth('FileName version 1.11 • ©1987 Steve Maller');
  276.  
  277.             END; { PROCEDURE FileName }
  278.  
  279. END.
  280.